#include <main.h>

void tftInit(){
  Serial.println("[info]tft init...");
  tft.begin(); /* TFT init */
  tft.invertDisplay(1);//反转所有显示颜色：1反转，0正常
  //1-3是90度到270度旋转
  // tft.setRotation(0); // pcb version
  tft.setRotation(2);   // nodemcu version
  tft.fillScreen(0x0000);
  tft.setTextColor(TFT_BLACK, bgColor);
  Serial.println("[info]tft init finish");

  TJpgDec.setJpgScale(1);
  TJpgDec.setSwapBytes(true);
  TJpgDec.setCallback(tft_output);
}
//TFT屏幕输出函数
bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap)
{
  if ( y >= tft.height() ) return 0;
  tft.pushImage(x, y, w, h, bitmap);
  // Return 1 to decode next block
  return 1;
}

void imgAnim()
{
  // Serial.println("[info] imgAnim start"); 
  int x=160,y=160;
  if(millis() - AprevTime > 37) //37 ms切换一次
  {
    Anim++;
    AprevTime = millis();
  }
  if(Anim==10)
    Anim=0;

  switch(Anim)
  {
    case 0:
      TJpgDec.drawJpg(x,y,i0, sizeof(i0));
      break;
    case 1:
      TJpgDec.drawJpg(x,y,i1, sizeof(i1));
      break;
    case 2:
      TJpgDec.drawJpg(x,y,i2, sizeof(i2));
      break;
    case 3:
      TJpgDec.drawJpg(x,y,i3, sizeof(i3));
      break;
    case 4:
      TJpgDec.drawJpg(x,y,i4, sizeof(i4));
      break;
    case 5:
      TJpgDec.drawJpg(x,y,i5, sizeof(i5));
      break;
    case 6:
      TJpgDec.drawJpg(x,y,i6, sizeof(i6));
      break;
    case 7:
      TJpgDec.drawJpg(x,y,i7, sizeof(i7));
      break;
    case 8: 
      TJpgDec.drawJpg(x,y,i8, sizeof(i8));
      break;
    case 9: 
      TJpgDec.drawJpg(x,y,i9, sizeof(i9));
      break;
    default:
      Serial.println("显示Anim错误");
      break;
  }
}
void wifiInit(){
  // wifiMulti.addAP("LAPTOP9#337", "xy1229033519");
  // wifiMulti.addAP("MI9", "12345678"); 
  // wifiMulti.addAP("laptop_zeeland_5592", "12345678"); 
  // wl_status_t connectStatus = wifiMulti.run();   
  WiFi.begin("laptop_zeeland_5592", "12345678");
  Serial.println("[info] Connecting ...");                            
                        
  while (WiFi.status() != WL_CONNECTED) {
    renderSpriteLoading(30);
    if(loadNum>=194)SmartConfig();
    // renderSpriteWifiConnFailed();
  }   
  while(loadNum < 194) renderSpriteLoading(1);
  renderSpriteWifiConnSuccess();

  Serial.println('\n');
  Serial.print("Connected to ");
  Serial.println(WiFi.SSID());
  Serial.print("IP address:\t");
  Serial.println(WiFi.localIP());
}


void clientInit(){
  if ((WiFi.status() == WL_CONNECTED)) {
      Serial.println("[HTTP] begin...\n");
      if (http.begin(client, URL(server_url,api_hello))) {  // HTTP

        Serial.println("[HTTP] GET...\n");
        int httpCode = http.GET();

        if (httpCode > 0) {
          Serial.printf("[HTTP] GET... code: %d\n", httpCode);

          if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
            String payload = http.getString();
            Serial.println("[info] payload :"+payload);
            // 初始化成功后跳转
            renderSpriteServerSuccess(payload);
          }
        } else {
          Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
        }

        http.end();
      } else {
        Serial.printf("[HTTP} Unable to connect\n");
      }
    }

}


//进度条函数
void renderSpriteLoading(byte delayTime)//绘制进度条
{
  clk.setColorDepth(8);
  
  clk.createSprite(200, 100);
  clk.fillSprite(0x0000);  
  // clk.drawRoundRect(0,0,200,100,2,0xFFFF);      
  clk.drawRoundRect(0,0,200,16,8,0xFFFF);      
  clk.fillRoundRect(3,3,loadNum,10,6,0xFFFF); 
  clk.setTextDatum(CC_DATUM); 
  clk.setTextColor(TFT_GREEN, 0x0000); 
  clk.drawString("Connecting to WiFi......",100,40,2);
  clk.setTextColor(TFT_WHITE, 0x0000); 
  clk.drawString(String(VERSION)+" by "+String(AUTHOR),100,60,2);
  clk.pushSprite(20,120); 
  clk.deleteSprite();
  loadNum += 1;
  delay(delayTime);
}

void renderSpriteWifiConnFailed(){
  clk.setColorDepth(8);
  clk.createSprite(200, 60);
  clk.fillSprite(0x0000); 
  clk.setTextDatum(CC_DATUM);  
  clk.setTextColor(TFT_GREEN, 0x0000); 
  clk.drawString("WiFi Connect Fail!",100,10,2);
  clk.drawString("SSID:",45,40,2);
  clk.setTextColor(TFT_WHITE, 0x0000); 
  clk.drawString("AutoConnectAP",125,40,2);
  clk.pushSprite(20,50);  
    
  clk.deleteSprite();
}

void renderSpriteWifiConnSuccess(){
  clk.setColorDepth(8);
  clk.createSprite(200, 70);//创建窗口
  clk.fillSprite(0x0000);   //填充率
  clk.setTextDatum(CC_DATUM);   //设置文本数据
  // clk.setTextColor(TFT_GREEN, 0x0000); 
  // clk.drawString("Connect to Config:",70,10,2);
  clk.setTextColor(TFT_WHITE, 0x0000); 
  clk.drawString("has connected",100,40,4);
  clk.pushSprite(20,40);  //窗口位置
  clk.deleteSprite();
}

void renderSpriteServerSuccess(String input){
  DynamicJsonDocument doc(1024);
  DeserializationError error = deserializeJson(doc, input);
  if (error) {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.f_str());
    return;
  }
  const char* msg = doc["msg"]; // "success"
  const char* data = doc["data"]; // "Hello World"
  int code = doc["code"]; // 200
  Serial.print("msg = ");Serial.println(msg);
  Serial.print("data = ");Serial.println(data);
  Serial.print("code = ");Serial.println(code);
  
  clk.setColorDepth(8);
  clk.createSprite(200, 70);
  clk.fillSprite(0x0000); 
  clk.setTextDatum(CC_DATUM); 
  clk.setTextColor(TFT_GREEN, 0x0000); 
  clk.drawString("server information",70,10,2);
  clk.setTextColor(TFT_WHITE, 0x0000); 
  clk.drawString(data,100,40,4);
  clk.pushSprite(20,40);
  clk.deleteSprite();
  delay(1000);
}

String httpGet(String url){
  if ((WiFi.status() == WL_CONNECTED)) {

    if (http.begin(client, url)) {
      int httpCode = http.GET();
      Serial.printf("[HTTP] GET... code: %d\n", httpCode);
      
      if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
        String payload = http.getString();
        Serial.println("[info] payload: "+payload);
        http.end();
        return payload;
      }
      http.end();
      renderSpritePageHomeError();
    } else {
      Serial.printf("[HTTP} Unable to connect\n");
    }
  }
  return "";
}

//微信配网
void SmartConfig()
{
  WiFi.mode(WIFI_STA);    //设置STA模式
  //tft.pushImage(0, 0, 240, 240, qr);
  tft.pushImage(0, 0, 240, 240, qr);
  Serial.println("\r\nWait for Smartconfig...");    //打印log信息
  WiFi.beginSmartConfig();      //开始SmartConfig，等待手机端发出用户名和密码
  while (1)
  {
    Serial.println("等待中...");
    delay(1000);                   // wait for a second
    if (WiFi.smartConfigDone())//配网成功，接收到SSID和密码
    {
    Serial.println("SmartConfig Success");
    Serial.printf("SSID:%s\r\n", WiFi.SSID().c_str());
    Serial.printf("PSW:%s\r\n", WiFi.psk().c_str());
    break;
    }
  }
  loadNum = 194;
  renderSpriteBlank();
}

// parse the json of page home
listing_info * homeParser(String res){
  listing_info *listingInfo = new listing_info();

  DynamicJsonDocument doc(1024);
  deserializeJson(doc, res);
  JsonObject root = doc.as<JsonObject>();
  JsonObject jsonData = root["data"];
  String listings = jsonData["listings"].as<String>();

  // devide listings split by '^'
  String * recArr = new String[100];
  int recArrIndex = 0;
  char * tempArr = new char[listings.length()+1];
  strcpy(tempArr,listings.c_str());
  char * divideSign = new char[2];
  strcpy(divideSign,"^");

  char * p = strtok(tempArr,divideSign);
  while(p){
    String s = p;
    recArr[recArrIndex++] = s;
    p = strtok(NULL,divideSign);
  }

  // iterate all element in recArr
  for(int i = 0;i < recArr->length();i++){
    if(recArr[i] == NULL){
      listingInfo->size = i;
      break;
    }
    // Serial.println("[info:parse] Listing item :"+recArr[i]);
  }
  // Serial.println("[info:parse] Listing size :"+String(listingInfo->size));

  listingInfo->listing = recArr;
  return listingInfo;
}

void renderSpritePageHome(){
  Serial.println("[info] render sprite page listing");
  // testing ....  font version
  // clk.setColorDepth(8);
  // clk.loadFont(ZdyLwFont_20);  
  // clk.createSprite(190,190); 
  // clk.fillSprite(bgColor);
  // clk.setTextDatum(CC_DATUM);
  // clk.setTextColor(TFT_WHITE, bgColor); 
  // clk.drawString("1.finish my homework1",120,20);
  // clk.drawString("2.finish homework2",120,60);
  // clk.drawString("2.finish homework2",120,100);
  // clk.drawString("3.finish my homework3",120,160);
  // clk.pushSprite(20,20);
  // clk.deleteSprite();


  // normal version with no font
  clk.setColorDepth(8);
  clk.createSprite(200,200);
  clk.fillSprite(0x0000);
  clk.setTextDatum(CC_DATUM);
  clk.setTextColor(TFT_WHITE, 0x0000);
  clk.drawString("CPU : 15%",100,30,4); 
  clk.drawString("Thread : 29%",100,60,4); 
  clk.drawString("Memory : 398MB",100,90,4); 
  clk.drawString("PID : 16283",100,120,4); 
  clk.pushSprite(20,20);
  clk.deleteSprite();
}

void renderSpritePageListing(listing_info *listing){
  Serial.println("[info] render sprite page listing start");
  int step = 20;
  clk.setColorDepth(8);
  clk.createSprite(200,200);
  clk.fillSprite(0x0000);
  clk.setTextDatum(CC_DATUM);
  clk.setTextColor(TFT_WHITE, 0x0000);
  clk.drawRect(0,0,200,200,TFT_WHITE);
  
  for(int i=0;i< listing->size;i++){
    String content = listing->listing[i];
    // clk.drawString(content,100,step,4); 
    clk.drawString(content,100,step,2); 
    step += 30;
  }
  clk.pushSprite(20,20);
  clk.deleteSprite();
  Serial.println("[info page_listing] render sprite page listing end");
}

void renderSpritePageInit(){
  clk.setColorDepth(8);
  clk.createSprite(200,200);
  clk.fillSprite(0x0000);
  clk.setTextDatum(CC_DATUM);
  clk.setTextColor(TFT_WHITE, 0x0000);
  clk.drawString("Spire",100,100,4);
  clk.pushSprite(20,20);
  clk.deleteSprite();
  delay(1500);

  clk.setColorDepth(8);
  clk.createSprite(200,200);
  clk.fillSprite(0x0000);
  clk.setTextDatum(CC_DATUM);
  clk.setTextColor(TFT_WHITE, 0x0000);
  clk.drawString("Desiged by",80,100,4);
  clk.drawString(AUTHOR,150,130,4);
  clk.pushSprite(20,20);
  clk.deleteSprite();
  delay(1500);
  renderSpriteBlank();
}
void renderSpriteBlank(){
  clk.setColorDepth(8);
  clk.createSprite(200,200);
  clk.fillSprite(0x0000);
  clk.pushSprite(20,20);
  clk.deleteSprite();
}

void renderSpritePageHomeError(){
  clk.setColorDepth(8);
  clk.createSprite(200,200);
  clk.fillSprite(0x0000);
  clk.setTextDatum(CC_DATUM);
  clk.setTextColor(TFT_WHITE, 0x0000);
  clk.drawString("404 NOT FOUND",100,100,4);
  clk.pushSprite(20,20);
  clk.deleteSprite();
}

void clockTick(){
  timeStamp += 10;
  // Serial.println("[info] tick"+String(timeStamp));
}

void renderSpriteRefresh(){
  String res = "" ;
  
  if(custom_timeStamp % 1000 == 0){
    Serial.println("[tick] 1s tick");
    switch (MODE)
    {
    case MODE_HOME:
      renderSpritePageHome();
      break;
    case MODE_LISTING:
      res = httpGet(URL(server_url,api_get_listing));
      if(res!=""){
        renderSpritePageListing(homeParser(res));
      }
      break;
    default:
      break;
    }
  }
  // show picture animation
  // if(timeStamp % 50 == 0){
  //   imgAnim();
  // }
}

void setup() {
  Serial.begin(115200);
  Serial.println("[info] version: " VERSION);
  Serial.println("[info] author: " AUTHOR);
  // ticker1.attach(0.01,clockTick);

  pinMode(LCD_BL_PIN, OUTPUT);
  analogWrite(LCD_BL_PIN, 1023 - (LCD_BL_PWM*10));
  
  tftInit();
  // MODE = MODE_LISTING;
  MODE = MODE_HOME;
  // renderSpritePageInit();

  wifiInit();
  delay(1000);
  if(WiFi.status() == WL_CONNECTED){
    clientInit();
  }
  
}

void loop(){
  renderSpriteRefresh();
  custom_timeStamp += 10;
  // Serial.println("[info] custom_timeStamp: "+String(custom_timeStamp));
  delay(10);
}